using System;
using System.Globalization;

namespace Viyi.Util
{
    partial class StringUtil
    {
        /// <summary>
        /// 将字符串转换为<c>Nullable&lt;DateTime&gt;</c>类型。
        /// </summary>
        /// <param name="s">源字符串</param>
        /// <param name="style">源字符串描述日期/时间的样式</param>
        /// <returns>转换得到的<c>DateTime?</c>对象，若转换失败返回<c>null</c>。</returns>
        public static DateTime? ToDateTime(this string s, DateTimeStyles style)
        {
            DateTime value;
            return DateTime.TryParse(s, DateTimeFormatInfo.CurrentInfo, style, out value)
                ? (DateTime?) value
                : null;
        }

        /// <summary>
        /// 将字符串转换为<c>DateTime</c>类型。
        /// </summary>
        /// <param name="s">源字符串</param>
        /// <param name="style">源字符串描述日期/时间的样式</param>
        /// <param name="defaultValue">转换失败时返回的默认值</param>
        /// <returns>转换得到的<c>DateTime</c>值，若转换失败返回<c>defaultValue</c>。</returns>
        public static DateTime ToDateTime(this string s, DateTimeStyles style, DateTime defaultValue)
        {
            DateTime value;
            return DateTime.TryParse(s, DateTimeFormatInfo.CurrentInfo, style, out value)
                ? value
                : defaultValue;
        }

        /// <summary>
        /// 按默认的样式将字符串转换为<c>Nullable&lt;DateTime&gt;</c>类型。
        /// </summary>
        /// <param name="s">源字符串</param>
        /// <returns>转换得到的<c>DateTime?</c>对象，若转换失败返回<c>null</c>。</returns>
        public static DateTime? ToDateTime(this string s)
        {
            DateTime value;
            return DateTime.TryParse(s, out value) ? (DateTime?) value : null;
        }

        /// <summary>
        /// 将字符串转换为<c>DateTime</c>类型。
        /// </summary>
        /// <param name="s">源字符串</param>
        /// <param name="defaultValue">转换失败时返回的默认值</param>
        /// <returns>转换得到的<c>DateTime</c>值，若转换失败返回<c>defaultValue</c>。</returns>
        public static DateTime ToDateTime(this string s, DateTime defaultValue)
        {
            DateTime value;
            return DateTime.TryParse(s, out value) ? value : defaultValue;
        }

        /// <summary>
        /// 按指定的格式将字符串转换为<c>Nullable&lt;DateTime&gt;</c>类型。
        /// </summary>
        /// <param name="s">源字符串</param>
        /// <param name="isEscapeSlash">是否先对斜线(/)字符进行转义</param>
        /// <param name="formats">格式。<see cref="DateTime.TryParseExact(String, String[], IFormatProvider, DateTimeStyles, out DateTime)"/></param>
        /// <returns>转换得到的<c>DateTime?</c>对象，若转换失败返回<c>null</c>。</returns>
        public static DateTime? ToDateTime(this string s, bool isEscapeSlash,
            params string[] formats)
        {
            if (isEscapeSlash)
            {
                var newFormats = new string[formats.Length];
                for (int i = 0; i < newFormats.Length; i++)
                {
                    newFormats[i] = formats[i].Replace("/", @"\/");
                }
                return s.ToDateTime(newFormats);
            }
            else
            {
                return s.ToDateTime(formats);
            }
        }

        /// <summary>
        /// 按指定的格式将字符串转换为<c>Nullable&lt;DateTime&gt;</c>类型。
        /// </summary>
        /// <param name="s">源字符串</param>
        /// <param name="formats">格式。<see cref="DateTime.TryParseExact(String, String[], IFormatProvider, DateTimeStyles, out DateTime)"/></param>
        /// <returns>转换得到的<c>DateTime?</c>对象，若转换失败返回<c>null</c>。</returns>
        public static DateTime? ToDateTime(this string s, params string[] formats)
        {
            DateTime value;
            bool r = formats != null && formats.Length == 1
                ? DateTime.TryParseExact(s, formats[0],
                    DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out value)
                : DateTime.TryParseExact(s, formats,
                    DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out value);
            return r ? (DateTime?) value : null;
        }

        /// <summary>
        /// 将字符串转换为<c>DateTime</c>类型。
        /// </summary>
        /// <param name="s">源字符串</param>
        /// <param name="defaultValue"></param>
        /// <param name="formats">格式。<see cref="DateTime.TryParseExact(String, String[], IFormatProvider, DateTimeStyles, out DateTime)"/></param>
        /// <returns>转换得到的<c>DateTime</c>值，若转换失败返回<c>defaultValue</c>。</returns>
        public static DateTime ToDateTime(this string s, DateTime defaultValue, params string[] formats)
        {
            DateTime value;
            bool r = formats != null && formats.Length == 1
                ? DateTime.TryParseExact(s, formats[0],
                DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out value)
                : DateTime.TryParseExact(s, formats,
                DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out value);
            return r ? value : defaultValue;
        }
    }
}
